#include "rubik.h"
#include <sstream>
rubik::rubik() {

	bool noColor = true;

	deg_x=0;
	deg_y=0;
	deg_z=0;
	solutioncount = -1;

	// initialize all necessary cubes
	int l = 0;
	for (double z=.3; z>=-.3; z-=.3) {
		for (double y=.3; y>=-.3; y-=.3) {
			for (double x=-.3; x<=.3; x+=.3) {
				cubes[l] = new cube (vec3 (x, y, z));
				l++;
			}
		}
	}

	// initialize cube locations to default false

	for (int i=0; i<27;i++) {
		cubes[i]->location[TOP]=
			cubes[i]->location[BOTTOM]=
			cubes[i]->location[FORWARD]=
			cubes[i]->location[BACKWARD]=
			cubes[i]->location[LEFT]=
			cubes[i]->location[RIGHT]=
			cubes[i]->location[MIDDLE_X]=
			cubes[i]->location[MIDDLE_Y]=
			cubes[i]->location[MIDDLE_Z]=false;
	}

	// Associate the smaller cubes with the overall side of the Rubik's Cube

	// Set first set of 9 cubes z=+.3
	cubes[0]->location[FORWARD]=cubes[0]->location[TOP]=cubes[0]->location[LEFT]=true;
	cubes[1]->location[FORWARD]=cubes[1]->location[TOP]=cubes[1]->location[MIDDLE_Y]=true;
	cubes[2]->location[FORWARD]=cubes[2]->location[TOP]=cubes[2]->location[RIGHT]=true;

	cubes[3]->location[FORWARD]=cubes[3]->location[MIDDLE_Z]=cubes[3]->location[LEFT]=true;
	cubes[4]->location[FORWARD]=cubes[4]->location[MIDDLE_Z]=cubes[4]->location[MIDDLE_Y]=true;
	cubes[5]->location[FORWARD]=cubes[5]->location[RIGHT]=cubes[5]->location[MIDDLE_Z]=true;

	cubes[6]->location[FORWARD]=cubes[6]->location[BOTTOM]=cubes[6]->location[LEFT]=true;
	cubes[7]->location[FORWARD]=cubes[7]->location[BOTTOM]=cubes[7]->location[MIDDLE_Y]=true;
	cubes[8]->location[FORWARD]=cubes[8]->location[BOTTOM]=cubes[8]->location[RIGHT]=true;

	// Set next set of 9 cubes z=0
	cubes[9]->location[MIDDLE_X]=cubes[9]->location[TOP]=cubes[9]->location[LEFT]=true;
	cubes[10]->location[MIDDLE_X]=cubes[10]->location[TOP]=cubes[10]->location[MIDDLE_Y]=true;
	cubes[11]->location[MIDDLE_X]=cubes[11]->location[TOP]=cubes[11]->location[RIGHT]=true;

	cubes[12]->location[MIDDLE_X]=cubes[12]->location[MIDDLE_Z]=cubes[12]->location[LEFT]=true;
	cubes[13]->location[MIDDLE_X]=cubes[13]->location[MIDDLE_Z]=cubes[13]->location[MIDDLE_Y]=true;
	cubes[14]->location[MIDDLE_X]=cubes[14]->location[MIDDLE_Z]=cubes[14]->location[RIGHT]=true;

	cubes[15]->location[MIDDLE_X]=cubes[15]->location[BOTTOM]=cubes[15]->location[LEFT]=true;
	cubes[16]->location[MIDDLE_X]=cubes[16]->location[BOTTOM]=cubes[16]->location[MIDDLE_Y]=true;
	cubes[17]->location[MIDDLE_X]=cubes[17]->location[BOTTOM]=cubes[17]->location[RIGHT]=true;

	// Set next set of 9 cubes z=-.3
	cubes[18]->location[BACKWARD]=cubes[18]->location[TOP]=cubes[18]->location[LEFT]=true;
	cubes[19]->location[BACKWARD]=cubes[19]->location[TOP]=cubes[19]->location[MIDDLE_Y]=true;
	cubes[20]->location[BACKWARD]=cubes[20]->location[TOP]=cubes[20]->location[RIGHT]=true;

	cubes[21]->location[BACKWARD]=cubes[21]->location[MIDDLE_Z]=cubes[21]->location[LEFT]=true;
	cubes[22]->location[BACKWARD]=cubes[22]->location[MIDDLE_Z]=cubes[22]->location[MIDDLE_Y]=true;
	cubes[23]->location[BACKWARD]=cubes[23]->location[MIDDLE_Z]=cubes[23]->location[RIGHT]=true;

	cubes[24]->location[BACKWARD]=cubes[24]->location[BOTTOM]=cubes[24]->location[LEFT]=true;
	cubes[25]->location[BACKWARD]=cubes[25]->location[BOTTOM]=cubes[25]->location[MIDDLE_Y]=true;
	cubes[26]->location[BACKWARD]=cubes[26]->location[BOTTOM]=cubes[26]->location[RIGHT]=true;

	// Set the CURRENT orientation
	orient.setOrientation(FORWARD, TOP);
	
	// TODO correctly Set CURRENT orientation
	myLeft=LEFT;
	myRight=RIGHT;
	myTop=TOP;
	myBottom=BOTTOM;

	// Set the Faces in order so it can be exported for logic use.
	// if (normal_Mode) also set color, else leave it to color Mode.
	
	int T_buffer = 18;
	int D_buffer = 6;
	int L_buffer = 18;
	int R_buffer = 2;
	int B_buffer = 20;

	for (int j=0, counter=0; j<9; j++, counter++) {
		
		if (counter == 3) {
			counter = 0;
			T_buffer-=9;
			D_buffer+=9;
			L_buffer+=3;
			R_buffer+=3;
			B_buffer+=3;
		}
		
		faces[j] = cubes[T_buffer+counter]->myFaces[T];
		faces[j]->id=j;
		faces[j+9] = cubes[D_buffer+counter]->myFaces[D];
		faces[j+9]->id=j+9;
		faces[j+18] = cubes[L_buffer-(9*counter)]->myFaces[L];
		faces[j+18]->id=j+18;
		faces[j+27] = cubes[R_buffer+(9*counter)]->myFaces[R];
		faces[j+27]->id=j+27;
		faces[j+36] = cubes[j]->myFaces[F];
		faces[j+36]->id=j+36;
		faces[j+45] = cubes[B_buffer-counter]->myFaces[B];
		faces[j+45]->id=j+45;		
		

		if (noColor) {
			//please don't change these numbers. Our code isn't that elegant. These colors are hardcoded in two other places.
			//colorpad and color2int
			faces[j]->color=vec3(.9,.9,.9);
			faces[j+9]->color=vec3(0.4,0.4,0);
			faces[j+18]->color=vec3(0,0,0.4);
			faces[j+27]->color=vec3(0,0.4,0);
			faces[j+36]->color=vec3(.8,.35,0);
			faces[j+45]->color=vec3(.4,0,0);
		}
	}
}

RUBIK_SIDES getSide (int indA) {
	if (indA >= 0 && indA <9) {
		return TOP;
	} else if (indA >= 9 && indA <18) {
		return BOTTOM;
	} else if (indA >= 18 && indA < 27) {
		return LEFT;
	} else if (indA >=27 && indA<36) {
		return RIGHT;
	} else if (indA >=36 && indA<45) {
		return FORWARD;
	} else if (indA >=45 && indA<54) {
		return BACKWARD;
	}
}
void rubik::rotateFace(int indA, int indB, RUBIK_ROTATE r) {
	
	C_Face *f[9];
	cout << indA << endl;
	for (int j=0; j<9; j++) {
			f[j]=faces[j+indA];
		}

	vec3 tempv [9];
	for (int j=0; j<9; j++) {
		tempv[j]=faces[j+indA]->color;
	}


	switch (r) {

	case CW:
		faces[indA]->color=tempv[6];
		faces[indA+1]->color=tempv[3];
		faces[indA+2]->color=tempv[0];
		faces[indA+3]->color=tempv[7];
		faces[indA+4]->color=tempv[4];
		faces[indA+5]->color=tempv[1];
		faces[indA+6]->color=tempv[8];
		faces[indA+7]->color=tempv[5];
		faces[indA+8]->color=tempv[2];
		/*
		faces[indA]=f[6];
		faces[indA+1]=f[3];
		faces[indA+2]=f[0];
		faces[indA+3]=f[7];
		faces[indA+4]=f[4];
		faces[indA+5]=f[1];
		faces[indA+6]=f[8];
		faces[indA+7]=f[5];
		faces[indA+8]=f[2];
		*/
		break;
	case CCW:
		faces[indA]->color=tempv[2];
		faces[indA+1]->color=tempv[5];
		faces[indA+2]->color=tempv[8];
		faces[indA+3]->color=tempv[1];
		faces[indA+4]->color=tempv[4];
		faces[indA+5]->color=tempv[7];
		faces[indA+6]->color=tempv[0];
		faces[indA+7]->color=tempv[3];
		faces[indA+8]->color=tempv[6];
/*		
		faces[indA]=f[2];
		faces[indA+1]=f[5];
		faces[indA+2]=f[8];
		faces[indA+3]=f[1];
		faces[indA+4]=f[4];
		faces[indA+5]=f[7];
		faces[indA+6]=f[0];
		faces[indA+7]=f[3];
		faces[indA+8]=f[6];
*/		break;
	}

	reinitCubes();

}
void rubik::render() {

	glPushMatrix();

	glRotatef(deg_x,1,0,0);
	glRotatef(deg_y,0,1,0);
	glRotatef(deg_z,0,0,1);

	for (int i=0; i<27; i++){
		cubes[i]->drawCube();
	}
	glPopMatrix();
}
void rubik::reset() {
	for (int i=0;i<26;i++) {
		cubes[i]->setY(0);
		cubes[i]->resetX();
		cubes[i]->resetY();
		cubes[i]->resetZ();
	}
}
//x y are screen coordinates
void rubik::resetFaceColor(float x, float y, vec3 *c){
	cout << "Checking faces" << endl;
	for (int i=0;i<54;i++){
		if (intersect(positions[i],facet_w, facet_h, x,y)){
			cout << "reset face color" << endl;
			faces[i]->color = *c;
			break;
		}
	}
}
void rubik::renderflat(){
	int wwidth = glutGet(GLUT_WINDOW_WIDTH);
	int wheight = glutGet(GLUT_WINDOW_HEIGHT);

	wwidth = min(wwidth,wheight);
	wheight = wwidth;

	float onefourthw = float(wwidth)/4;
	float onethirdh = float(wheight)/4;

	float width = onefourthw/3;
	float height = onethirdh/3;

	this->facet_h = height;
	this->facet_w = width;


	//top face
	float ini_x=0-float(wwidth)/2+onefourthw;
	float cur_y=0+float(wheight)/2;
	float cur_x;
	for (int i=0;i< 9;i++){
		int pos = i % 3;
		if (pos == 0) {
			cur_x = ini_x;
		} else {
			cur_x += width;
		}

		faces[i]->drawFlatFace(vec2(cur_x,cur_y),width,height);
		this->positions[i] = vec2(cur_x,cur_y);
		

		if (pos == 2) cur_y -= height;
	}

					//bottom
	ini_x = 0 - float(wwidth)/2 + onefourthw;
	cur_y = 0 + float(wheight)/2 - 2*onethirdh;
	
	for (int i=9;i<18;i++){
		int pos = i % 3;
		if (pos == 0) {
				cur_x = ini_x;
		} else {
			cur_x += width;
		}
		faces[i]->drawFlatFace(vec2(cur_x,cur_y),width,height);
		this->positions[i] = vec2(cur_x,cur_y);
		
		if (pos == 2) cur_y -= height;
	}

	//left
	ini_x = 0 - float(wwidth)/2;
	cur_y = 0 + float(wheight)/2 - onethirdh;
	for (int i=18;i<27;i++){
		int pos = i % 3;
		if (pos == 0) {
			cur_x = ini_x;
		} else {
			cur_x += width;
		}
		faces[i]->drawFlatFace(vec2(cur_x,cur_y),width,height);
		this->positions[i] = vec2(cur_x,cur_y);
		
		if (pos == 2) cur_y -= height;
	}
	
				//right
	ini_x = 0 - float(wwidth)/2 + 2*onefourthw;
	cur_y = 0 + float(wheight)/2 - onethirdh;
	
	for (int i=27;i<36;i++){
		int pos = i % 3;
		if (pos == 0) {
				cur_x = ini_x;
		} else {
			cur_x += width;
		}
		faces[i]->drawFlatFace(vec2(cur_x,cur_y),width,height);
		this->positions[i] = vec2(cur_x,cur_y);
		
		if (pos == 2) cur_y -= height;
	}

		//front
	ini_x = 0 - float(wwidth)/2 + onefourthw;
	cur_y = 0 + float(wheight)/2 - onethirdh;
	
	for (int i=36;i<45;i++){
		int pos = i % 3;
		if (pos == 0) {
				cur_x = ini_x;
		} else {
			cur_x += width;
		}
		faces[i]->drawFlatFace(vec2(cur_x,cur_y),width,height);
		this->positions[i] = vec2(cur_x,cur_y);
		
		if (pos == 2) cur_y -= height;
	}


				//back
	ini_x = 0 - float(wwidth)/2 + 3*onefourthw;
	cur_y = 0 + float(wheight)/2 - onethirdh;
	
	for (int i=45;i<54;i++){
		int pos = i % 3;
		if (pos == 0) {
			cur_x = ini_x;
		} else {
			cur_x += width;
		}
		faces[i]->drawFlatFace(vec2(cur_x,cur_y),width,height);
		this->positions[i] = vec2(cur_x,cur_y);
		
		if (pos == 2) cur_y -= height;
	}


/*
	for (int i=0; i<54; i++){
		cout <<	i+1 << this->positions[i] << endl;
	}
	cout << "wwidth: " << wwidth << "whight: " <<wheight;
	cout << "width: " << width << "height: " << height;
	string foo;
	cin >> foo;
	*/
}

void rubik::makeRotation() {
	for (int i=0;i<27;i++) {
		if (cubes[i]->location[TOP]) {
			cubes[i]->setY(-3);
		}
	}
}

void rubik::rotateTY (RUBIK_ROTATE r){
	int step = (r==CCW) ? 3 : -3;
	for (int i=0;i<27;i++) {
		if (cubes[i]->location[TOP]) {
			cubes[i]->setY(step);
		}
	}
}
void rubik::rotateMY (RUBIK_ROTATE r){

	int step = (r==CCW) ? 3 : -3;
	for (int i=0;i<27;i++) {
		if (cubes[i]->location[MIDDLE_Z]) {
			cubes[i]->setY(step);
		}
	}
}

void rubik::rotateRZ (RUBIK_ROTATE r) {
	int step = (r==CCW) ? 3 : -3;
	for (int i=0;i<27;i++) {
		if (cubes[i]->location[FORWARD]) {
			cubes[i]->setZ(step);
		}
	}
}

void rubik::rotateLZ (RUBIK_ROTATE r) {
	int step = (r==CCW) ? 3 : -3;
	for (int i=0;i<27;i++) {
		if (cubes[i]->location[BACKWARD]) {
			cubes[i]->setZ(step);
		}
	}
}


void rubik::rotateLY (RUBIK_ROTATE r){
	int step = (r==CCW) ? -3 : 3;
	for (int i=0;i<27;i++) {
		if (cubes[i]->location[BOTTOM]) {
			cubes[i]->setY(step);
		}
	}
}
	
void rubik::rotateLX (RUBIK_ROTATE r){
	int step = (r==CCW) ? 3 : -3;
	for (int i=0;i<27;i++) {
		if (cubes[i]->location[LEFT]) {
			cubes[i]->setX(step);
		}
	}
}
void rubik::rotateMX (RUBIK_ROTATE r){
	int step = (r==CCW) ? 3 : -3;
	for (int i=0;i<27;i++) {
		if (cubes[i]->location[MIDDLE_Y]) {
			cubes[i]->setX(step);
		}
	}
}
void rubik::rotateRX (RUBIK_ROTATE r){
	int step = (r==CCW) ? 3 : -3;
	for (int i=0;i<27;i++) {
		if (cubes[i]->location[RIGHT]) {
			cubes[i]->setX(step);
		}
	}
}

void rubik::nextOrient(rotate_d d) {
	RUBIK_ORIENTATION &r = rubik::getOrientation();
	switch(r.frontSide) {
	case FORWARD:
		switch (r.topSide) {
			//DONE
		case TOP:

			switch (d) {
				//DONE
			case LEFT_D:
				r.frontSide=LEFT;
				break;
				//DONE
			case RIGHT_D:
				r.frontSide=RIGHT;
				break;
				//DONE
			case UP_D:
				r.frontSide=TOP;
				r.topSide=BACKWARD;
				break;
				//DONE
			case DOWN_D:
				r.frontSide=BOTTOM;
				r.topSide=FORWARD;
				break;
			}

			break;
			
		case BOTTOM:
			
			switch (d) {

			case LEFT_D:
				r.frontSide=RIGHT;
				break;
			case RIGHT_D:
				r.frontSide=LEFT;
				break;
			case UP_D:
				r.frontSide=BOTTOM;
				r.topSide=BACKWARD;
				break;
			case DOWN_D:
				r.frontSide=TOP;
				r.topSide=FORWARD;
				break;
			}

			break;
		case LEFT:
			switch (d) {

			case LEFT_D:
				r.frontSide=BOTTOM;
				break;
			case RIGHT_D:
				r.frontSide=TOP;
				break;
			case UP_D:
				r.frontSide=LEFT;
				r.topSide=BACKWARD;
				break;
			case DOWN_D:
				r.frontSide=RIGHT;
				r.topSide=FORWARD;
				break;
			}
			break;
		case RIGHT:
			switch (d) {

			case LEFT_D:
				r.frontSide=TOP;
				break;
			case RIGHT_D:
				r.frontSide=BOTTOM;
				break;
			case UP_D:
				r.frontSide=RIGHT;
				r.topSide=BACKWARD;
				break;
			case DOWN_D:
				r.frontSide=LEFT;
				r.topSide=FORWARD;
				break;
			}
			break;
		}
		break;
	case BACKWARD:
		switch (r.topSide) {
		//DONE
		case TOP:

			switch (d) {

			case LEFT_D:
				r.frontSide=RIGHT;
				break;
			case RIGHT_D:
				r.frontSide=LEFT;
				break;
			case UP_D:
				r.frontSide=TOP;
				r.topSide=FORWARD;
				break;
			case DOWN_D:
				r.frontSide=BOTTOM;
				r.topSide=BACKWARD;
				break;
			}

			break;
			//DONE
		case BOTTOM:
			
			switch (d) {

			case LEFT_D:
				r.frontSide=LEFT;
				break;
			case RIGHT_D:
				r.frontSide=RIGHT;
				break;
			case UP_D:
				r.frontSide=BOTTOM;
				r.topSide=FORWARD;
				break;
			case DOWN_D:
				r.frontSide=TOP;
				r.topSide=BACKWARD;
				break;
			}

			break;
		case LEFT:
			switch (d) {

			case LEFT_D:
				r.frontSide=TOP;
				break;
			case RIGHT_D:
				r.frontSide=BOTTOM;
				break;
			case UP_D:
				r.frontSide=LEFT;
				r.topSide=FORWARD;
				break;
			case DOWN_D:
				r.frontSide=RIGHT;
				r.topSide=BACKWARD;
				break;
			}
			break;
		case RIGHT:
			switch (d) {

			case LEFT_D:
				r.frontSide=BOTTOM;
				break;
			case RIGHT_D:
				r.frontSide=TOP;
				break;
			case UP_D:
				r.frontSide=RIGHT;
				r.topSide=FORWARD;
				break;
			case DOWN_D:
				r.frontSide=LEFT;
				r.topSide=BACKWARD;
				break;
			}
			break;
		}
		break;
	case LEFT:

		switch (r.topSide) {
		case TOP:

			switch (d) {

			case LEFT_D:
				r.frontSide=BACKWARD;
				break;
			case RIGHT_D:
				r.frontSide=FORWARD;
				break;
			case UP_D:
				r.frontSide=TOP;
				r.topSide=RIGHT;
				break;
			case DOWN_D:
				r.frontSide=BOTTOM;
				r.topSide=LEFT;
				break;
			}

			break;
		case BOTTOM:
			
			switch (d) {

			case LEFT_D:
				r.frontSide=FORWARD;
				break;
			case RIGHT_D:
				r.frontSide=BACKWARD;
				break;
			case UP_D:
				r.frontSide=BOTTOM;
				r.topSide=RIGHT;
				break;
			case DOWN_D:
				r.frontSide=TOP;
				r.topSide=LEFT;
				break;
			}

			break;
		case FORWARD:
			switch (d) {

			case LEFT_D:
				r.frontSide=TOP;
				break;
			case RIGHT_D:
				r.frontSide=BOTTOM;
				break;
			case UP_D:
				r.frontSide=FORWARD;
				r.topSide=RIGHT;
				break;
			case DOWN_D:
				r.frontSide=BACKWARD;
				r.topSide=LEFT;
				break;
			}
			break;
		case BACKWARD:
			switch (d) {

			case LEFT_D:
				r.frontSide=BOTTOM;
				break;
			case RIGHT_D:
				r.frontSide=TOP;
				break;
			case UP_D:
				r.frontSide=BACKWARD;
				r.topSide=RIGHT;
				break;
			case DOWN_D:
				r.frontSide=FORWARD;
				r.topSide=LEFT;
				break;
			}
			break;
		}

		break;
	case RIGHT:

		switch (r.topSide) {
		case TOP:

			switch (d) {

			case LEFT_D:
				r.frontSide=FORWARD;
				break;
			case RIGHT_D:
				r.frontSide=BACKWARD;
				break;
			case UP_D:
				r.frontSide=TOP;
				r.topSide=LEFT;
				break;
			case DOWN_D:
				r.frontSide=BOTTOM;
				r.topSide=RIGHT;
				break;
			}

			break;
		case BOTTOM:
			
			switch (d) {

			case LEFT_D:
				r.frontSide=BACKWARD;
				break;
			case RIGHT_D:
				r.frontSide=FORWARD;
				break;
			case UP_D:
				r.frontSide=BOTTOM;
				r.topSide=LEFT;
				break;
			case DOWN_D:
				r.frontSide=TOP;
				r.topSide=RIGHT;
				break;
			}

			break;
		case FORWARD:
			switch (d) {

			case LEFT_D:
				r.frontSide=BOTTOM;
				break;
			case RIGHT_D:
				r.frontSide=TOP;
				break;
			case UP_D:
				r.frontSide=FORWARD;
				r.topSide=LEFT;
				break;
			case DOWN_D:
				r.frontSide=BACKWARD;
				r.topSide=RIGHT;
				break;
			}
			break;
		case BACKWARD:
			switch (d) {

			case LEFT_D:
				r.frontSide=TOP;
				break;
			case RIGHT_D:
				r.frontSide=BOTTOM;
				break;
			case UP_D:
				r.frontSide=BACKWARD;
				r.topSide=LEFT;
				break;
			case DOWN_D:
				r.frontSide=FORWARD;
				r.topSide=RIGHT;
				break;
			}
			break;
		}
		break;
	case TOP:

		switch (r.topSide) {
		case BACKWARD:

			switch (d) {

			case LEFT_D:
				r.frontSide=LEFT;
				break;
			case RIGHT_D:
				r.frontSide=RIGHT;
				break;
			case UP_D:
				r.frontSide=BACKWARD;
				r.topSide=BOTTOM;
				break;
			case DOWN_D:
				r.frontSide=FORWARD;
				r.topSide=TOP;
				break;
			}

			break;
		case FORWARD:
			
			switch (d) {

			case LEFT_D:
				r.frontSide=RIGHT;
				break;
			case RIGHT_D:
				r.frontSide=LEFT;
				break;
			case UP_D:
				r.frontSide=FORWARD;
				r.topSide=BOTTOM;
				break;
			case DOWN_D:
				r.frontSide=BACKWARD;
				r.topSide=TOP;
				break;
			}

			break;
		case LEFT:
			switch (d) {

			case LEFT_D:
				r.frontSide=FORWARD;
				break;
			case RIGHT_D:
				r.frontSide=BACKWARD;
				break;
			case UP_D:
				r.frontSide=LEFT;
				r.topSide=BOTTOM;
				break;
			case DOWN_D:
				r.frontSide=RIGHT;
				r.topSide=TOP;
				break;
			}
			break;
		case RIGHT:
			switch (d) {

			case LEFT_D:
				r.frontSide=BACKWARD;
				break;
			case RIGHT_D:
				r.frontSide=FORWARD;
				break;
			case UP_D:
				r.frontSide=RIGHT;
				r.topSide=BOTTOM;
				break;
			case DOWN_D:
				r.frontSide=LEFT;
				r.topSide=TOP;
				break;
			}
			break;
		}

		break;
	case BOTTOM:

		switch (r.topSide) {
		case BACKWARD:

			switch (d) {

			case LEFT_D:
				r.frontSide=RIGHT;
				break;
			case RIGHT_D:
				r.frontSide=LEFT;
				break;
			case UP_D:
				r.frontSide=BACKWARD;
				r.topSide=TOP;
				break;
			case DOWN_D:
				r.frontSide=FORWARD;
				r.topSide=BOTTOM;
				break;
			}

			break;
		case FORWARD:
			
			switch (d) {

			case LEFT_D:
				r.frontSide=LEFT;
				break;
			case RIGHT_D:
				r.frontSide=RIGHT;
				break;
			case UP_D:
				r.frontSide=FORWARD;
				r.topSide=TOP;
				break;
			case DOWN_D:
				r.frontSide=BACKWARD;
				r.topSide=BOTTOM;
				break;
			}

			break;
		case LEFT:
			switch (d) {

			case LEFT_D:
				r.frontSide=BACKWARD;
				break;
			case RIGHT_D:
				r.frontSide=FORWARD;
				break;
			case UP_D:
				r.frontSide=LEFT;
				r.topSide=TOP;
				break;
			case DOWN_D:
				r.frontSide=RIGHT;
				r.topSide=BOTTOM;
				break;
			}
			break;
		case RIGHT:
			switch (d) {

			case LEFT_D:
				r.frontSide=FORWARD;
				break;
			case RIGHT_D:
				r.frontSide=BACKWARD;
				break;
			case UP_D:
				r.frontSide=RIGHT;
				r.topSide=TOP;
				break;
			case DOWN_D:
				r.frontSide=LEFT;
				r.topSide=BOTTOM;
				break;
			}
			break;
		}

		break;
	}
}

void rubik::test() {

	cout << cubes[6]->myFaces[F]->id;
	cout << " ";
	cout << cubes[7]->myFaces[F]->id;
	cout << " ";
	cout << cubes[8]->myFaces[F]->id;
	cout << " " << endl;
}

void rubik::rubikRotateY(RUBIK_ROTATE r){

	switch (r) {
	case CW:
		rotateMyFaces(TOP, CW);
		rotateMyFaces(MIDDLE_Y, CW);
		rotateMyFaces(BOTTOM, CCW);

		break;
	case CCW:
		rotateMyFaces(TOP, CCW);
		rotateMyFaces(MIDDLE_Y, CCW);
		rotateMyFaces(BOTTOM, CW);

		break;
	}
	reinitCubes();
}
void rubik::rubikRotateX(RUBIK_ROTATE r){

	switch (r) {
	case CW:
		rotateMyFaces(LEFT, CW);
		rotateMyFaces(MIDDLE_X, CW);
		rotateMyFaces(RIGHT, CCW);

		break;
	case CCW:
		rotateMyFaces(LEFT, CCW);
		rotateMyFaces(MIDDLE_X, CCW);
		rotateMyFaces(RIGHT, CW);

		break;
	}
	reinitCubes();
}
void rubik::rubikRotateZ(RUBIK_ROTATE r){}

void rubik::rotateSides(numset12 a, RUBIK_ROTATE r) {

	C_Face *f[12];

	for (int j=0; j<12; j++) {
		f[j]=faces[a.getNums(j)];
	}

	vec3 tempv [12];
	for (int j=0; j<12; j++) {

		tempv[j]=faces[a.getNums(j)]->color;
	}

	switch (r) {

	case CW:

		for (int k=0;k<12;k++) {
			faces[a.getNums(k)]->color=tempv[(k+9)%12];
		}
			reinitCubes();
		break;
	case CCW:

		for (int k=0;k<12;k++) {
			faces[a.getNums(k)]->color=tempv[((k+3)%12)];

		}
			reinitCubes();

			break;

	}

}

void rubik::rotateMyFaces(RUBIK_SIDES s, RUBIK_ROTATE r) {
	numset12 a;
	switch (s) {

	case TOP:
		a.setNums(47, 46, 45, 29, 28, 27, 38, 37, 36, 20, 19, 18);
		rotateSides(a,r);
		rotateFace(0,9,r);
		break;
	case BOTTOM:
		a.setNums(42, 43, 44, 33, 34, 35, 51, 52, 53, 24, 25, 26);
		rotateSides(a,r);
		rotateFace(9,18,r);
		break;
	case LEFT:
		a.setNums(0,3,6,36,39,42,9,12,15,53,50,47);
		rotateFace(18, 27, r);
		rotateSides(a,r);
		break;
		
	case RIGHT:
		a.setNums(44,41,38,8,5,2,45,48,51,17,14,11);
		rotateFace(27, 36, r);
		rotateSides(a,r);
		break;
	case FORWARD:
		a.setNums(26,23,20,6,7,8,27,30,33,11,10,9);
		rotateFace(36, 45, r);
		rotateSides(a,r);
		break;
	case BACKWARD:
		a.setNums(35,32,29,2,1,0,18,21,24,15,16,17);
		rotateFace(45, 54, r);
		rotateSides(a,r);
		break;
	case MIDDLE_X:
		a.setNums(1,4,7,37,40,43,10,13,16,52,49,46);
		rotateSides(a,r);
		break;
	case MIDDLE_Y:
		a.setNums(50,49,48,32,31,30,41,40,39,23,22,21);
		rotateSides(a,r);
		break;
	case MIDDLE_Z:
		a.setNums(25,22,19,3,4,5,28,31,34,14,13,12);
		rotateSides(a,r);
		break;
	}
	reinitCubes();
}

void rubik::reinitCubes() {

	// exchange Faces of cubes.

	int T_buffer = 18;
	int D_buffer = 6;
	int L_buffer = 18;
	int R_buffer = 2;
	int B_buffer = 20;

	for (int j=0, counter=0; j<9; j++, counter++) {
		
		if (counter == 3) {
			counter = 0;
			T_buffer-=9;
			D_buffer+=9;
			L_buffer+=3;
			R_buffer+=3;
			B_buffer+=3;
		}
		

		cubes[T_buffer+counter]->myFaces[T]=faces[j];
		cubes[D_buffer+counter]->myFaces[D]=faces[j+9];
		cubes[L_buffer-(9*counter)]->myFaces[L]=faces[j+18];
		cubes[R_buffer+(9*counter)]->myFaces[R]=faces[j+27];
		cubes[j]->myFaces[F]=faces[j+36];
		cubes[B_buffer-counter]->myFaces[B]=faces[j+45];
	}
}



void rubik::readSolution(string filename){
	ifstream solutionfile;
	string step;
	solutionfile.open(filename);
	cout << "Rubik::readSolution reading solution steps" << endl;
	this->solutions.clear();
	if (solutionfile.is_open()){
		while (!solutionfile.eof()){
		getline (solutionfile,step);
		this->solutions.push_back(step);
		}
	}
	solutioncount = -1;
	cout << "Finished importing solution steps" << endl;
}

int color2num(vec3 c){
	if (c == vec3(.9,.9,.9)){
		return 1;
	} else if (c == vec3(.4,.4,0)){
		return 2;
	} else if (c == vec3(0,0,.4)){
		return 3;
	} else if (c == vec3(0,.4,0)){
		return 4;
	} else if (c == vec3(.8,.35,0)){
		return 5;
	} else if (c == vec3(.4,0,0)){
		return 6;
	} else {
		return 0;
	}
}
void rubik::writeConfiguration(string filename){
	ofstream configfile;
	configfile.open(filename);
	string output("");
	stringstream out;
	//venk's order T,D,L,R,F,B
	//order needed T,L,F,R,B,D
	for (int i=0;i<9;i++){
		out << color2num(faces[i]->color);
	}
	for (int i=18;i<27;i++){
		out << color2num(faces[i]->color);
	}
	for (int i=36;i<45;i++){
		out << color2num(faces[i]->color);
	}
	for (int i=27;i<36;i++){
		out << color2num(faces[i]->color);
	}
	for (int i=45;i<54;i++){
		out << color2num(faces[i]->color);
	}
	for (int i=9;i<18;i++){
		out << color2num(faces[i]->color);
	}

	configfile << out.str() << endl;
	configfile.close();
}

void rubik::printSolutions(){
	int tmp = solutioncount;
	cout << "Solutions: " << endl;
	while(1){
		string step = nextSolution();
		if (step != ""){
			cout << step << endl;
		} else {
			cout << "Finished Printing Solutions" << endl;
			break;
		}
	}
	solutioncount = tmp;
}
string rubik::nextSolution(){
	if (solutioncount+1 < solutions.size()){
		return solutions.at(++solutioncount);
	} else {
		return "";
	}
}
	